import { Injectable, Optional, Inject } from '@angular/core';
import { NzModalService } from 'ng-zorro-antd';
import { HttpRequest, HttpHandler, HttpEvent, HttpErrorResponse } from '@angular/common/http';
import { Observable, ObservableInput, throwError } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';

import { ApplicationEnv, SESSION_CHECK_WHITELIST_PAGES, SPA } from '../keys';
import { Base } from '../view/base';
import { AppService } from '../service/app.service';
import { Steve } from '../steve';

@Injectable({
  providedIn: 'root'
})
export class InterceptorService<U, B, S> extends Base<U, B, S> {
  private showExpiresModal = false;
  private ACE;
  private _window;
  constructor(
    private nzModalService: NzModalService,
    private applicationEnv: ApplicationEnv,
    private appService: AppService<U, B, S>,
    @Optional() @Inject(SPA) private spa: boolean,
    @Optional() @Inject(SESSION_CHECK_WHITELIST_PAGES) private sessionWhiteListPages: string[]
  ) {
    super();
    this.spa = window.self === window.top ? (this.spa === null ? false : this.spa) : true;
    this.ACE = window.self === window.top ? window['ACE'] : window.top['ACE'];
    this._window = window.self === window.top ? window : window.top;
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const currentUser = this.storeService.getItem(('User') as any);
    const currentOrgId = currentUser && currentUser.currentOrg && currentUser.currentOrg.id ? currentUser.currentOrg.id + '' : '';
    const loginName = JSON.parse(this._window.localStorage.getItem('ACE_CLI_USER_INFO') || '{}').loginName || '';
    const saasTenantCode = this._window.localStorage.getItem('ACE_CLI_SAAS_TENANT_CODE');
    const ACE_CLI_TOKEN = this._window.localStorage.getItem('ACE_CLI_TOKEN');
    const saasTenantToken = this._window.localStorage.getItem('ACE_CLI_SAAS_TENANT_TOKEN');
    const _headers: any = {
      currentorgid: currentOrgId,
      saastenantcode: saasTenantCode,
      saastenanttoken: saasTenantToken,
      token: ACE_CLI_TOKEN,
      loginname: loginName,
    };

    if (this.spa && currentOrgId === '') {
      _headers.groupType = currentUser.currentOrg.ouTypeId;
      _headers.groupCode = currentUser.currentOrg.code;
    }

    const _req = req.clone({
      withCredentials: false,
      setHeaders: {
        ..._headers,
      }
    });

    return next.handle(_req).pipe(
      // 处理http协议异常
      catchError((e: HttpErrorResponse, caught: Observable<any>): ObservableInput<any> => {
        // 当status === 0 时，可能出现的问题，请求跨域失败，302跨域失败。判断session失效或者超时，重定向到授权页面
        if (e.status === 0 && e.url.includes(this.applicationEnv.apiPath)) {
          // 如果存在会话校验白名单并且当前页面符合白名单则直接跳转到认证页面
          if (this.sessionWhiteListPages) {
            const currUrl = this.router.url;
            for (let i = 0; i < this.sessionWhiteListPages.length; i++) {
              const page = this.sessionWhiteListPages[i];
              const pageRex = new RegExp(page, 'i');
              if (pageRex.test(currUrl)) {
                this.appService.storeSession();
                if (!this.spa) {
                  window.location.href = this.applicationEnv.authUrl;
                } else {
                  this.ACE.login();
                }
                return throwError(e);
              }
            }
          }

          this.steve.setGlobalItem('is_session_invalid', true);
          if (!this.showExpiresModal) {
            this.showExpiresModal = true;
            this.nzModalService.confirm({
              nzTitle: this.i18nService.getValue('@hint'),
              nzContent: this.i18nService.getValue('@login-expiration'),
              nzOkText: this.i18nService.getValue('@ok'),
              nzOnOk: () => {
                this.appService.storeSession();
                if (!this.spa) {
                  window.location.href = this.applicationEnv.authUrl;
                } else {
                  this.ACE.login();
                }
              },
              nzOnCancel: () => {
                this.showExpiresModal = false;
              }
            });
          }

          return throwError(e);
        } else if (e.status === 403) {
          this.router.navigate(['/403'], { queryParams: { type: 'api' } });
          return throwError(e);
        }

        // 根据http协议状态码提示对应信息
        let notice = '';
        if (e.status >= 500) {
          notice = this.i18nService.getValue('@fwfm');
        } else if (e.status === 400) {
          notice = this.i18nService.getValue('@csyc');
        } else if (e.status === 404) {
          notice = this.i18nService.getValue('@jkwx');
        }

        (<any>e)._notice = notice;

        return throwError(e);
      }),
      // 处理业务异常
      tap((event) => {
        // ...
      })
    );
  }

}
